﻿using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Linq;
using HtmlAgilityPack;

class Program
{
    static HttpClient client = new HttpClient();
    static Dictionary<string, List<string>> phoneNumbers = new Dictionary<string, List<string>>();
    static HashSet<string> visitedUrls = new HashSet<string>();
    static void Main(string[] args)
    {
        Console.OutputEncoding = System.Text.Encoding.UTF8;
        MainAsync(args).GetAwaiter().GetResult();
    }
    static async Task MainAsync(string[] args)
    {
        Console.WriteLine("请输入要搜索的关键字：");
        string keyword = Console.ReadLine();

        List<string> searchResults = await SearchUrlsFromBaiduAsync(keyword);

        var tasks = searchResults.Select(url => ProcessUrlAsync(url));
        await Task.WhenAll(tasks);

        Console.WriteLine("\n已爬取的URL：");
        foreach (var url in visitedUrls)
        {
            Console.WriteLine(url);
        }

        Console.WriteLine($"\n找到的电话号码（共 {phoneNumbers.Count} 个）：");
        foreach (var phone in phoneNumbers)
        {
            Console.WriteLine($"号码: {phone.Key}");
            foreach (var url in phone.Value)
            {
                Console.WriteLine($"  来源: {url}");
            }
        }
    }

    static async Task<List<string>> SearchUrlsFromBaiduAsync(string keyword)
    {
        List<string> urls = new List<string>();
        try
        {
            string searchUrl = $"https://www.baidu.com/s?wd={Uri.EscapeDataString(keyword + " 高校 电话号码")}";

            client.DefaultRequestHeaders.UserAgent.ParseAdd("Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
            var response = await client.GetStringAsync(searchUrl);

            HtmlDocument doc = new HtmlDocument();
            doc.LoadHtml(response);

            var nodes = doc.DocumentNode.SelectNodes("//h3[contains(@class,'t')]/a");

            if (nodes != null)
            {
                foreach (var node in nodes)
                {
                    var href = node.GetAttributeValue("href", "");
                    if (!string.IsNullOrEmpty(href) && href.StartsWith("http"))
                    {
                        string realUrl = await GetRealUrlAsync(href);
                        if (!string.IsNullOrEmpty(realUrl))
                        {
                            urls.Add(realUrl);
                        }
                    }
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("百度搜索失败：" + ex.Message);
        }

        return urls;
    }

    static async Task<string> GetRealUrlAsync(string baiduUrl)
    {
        try
        {
            var response = await client.GetAsync(baiduUrl);
            if (response.IsSuccessStatusCode)
            {
                return response.RequestMessage.RequestUri.ToString();
            }
        }
        catch (Exception)
        {
        }
        return null;
    }

    static async Task ProcessUrlAsync(string url)
    {
        if (visitedUrls.Contains(url)) return;

        try
        {
            var response = await client.GetStringAsync(url);
            visitedUrls.Add(url);

            var phones = ExtractPhoneNumbers(response);

            lock (phoneNumbers)
            {
                foreach (var phone in phones)
                {
                    if (!phoneNumbers.ContainsKey(phone))
                    {
                        phoneNumbers[phone] = new List<string>();
                    }
                    if (!phoneNumbers[phone].Contains(url))
                    {
                        phoneNumbers[phone].Add(url);
                    }
                    if (phoneNumbers.Count >= 100)
                        break;
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"访问失败：{url}，原因：{ex.Message}");
        }
    }

    static List<string> ExtractPhoneNumbers(string html)
    {
        List<string> phones = new List<string>();
        string pattern = @"((\+86)?(1\d{10})|(\d{3,4}-\d{7,8}))";
        MatchCollection matches = Regex.Matches(html, pattern);

        foreach (Match match in matches)
        {
            phones.Add(match.Value);
        }
        return phones.Distinct().ToList();
    }
}
